package com.ledi.guns.modular.ledipay.service.impl;

import java.io.Serializable;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import com.ledi.guns.common.persistence.dao.BillAlipayMapper;
import com.ledi.guns.common.persistence.dao.BillDetailMapper;
import com.ledi.guns.common.persistence.dao.BillWeixinMapper;
import com.ledi.guns.common.persistence.model.BillAlipay;
import com.ledi.guns.common.persistence.model.BillDetail;
import com.ledi.guns.common.persistence.model.BillWeixin;
import com.ledi.guns.core.util.SystemConstans;
import com.ledi.guns.modular.ledipay.controller.req.ScanCode.CloseBillInfo;
import com.ledi.guns.modular.ledipay.service.BillTimingService;

/**
 * 文件名称： com.ledi.guns.modular.ledipay.service.impl.BillTimingServiceImpl.java<br/>
 * 初始作者： 许芬<br/>
 * 创建日期： 2018年1月24日<br/>
 * 功能说明： 账单批处理任务<br/>
 * =================================================<br/>
 * 修改记录：<br/>
 * 修改作者 日期 修改内容<br/>
 * ================================================<br/>
 * Copyright (橘子股份-幼儿事业部) 2017-2018.All rights reserved.<br/>
 */
@Service
public class BillTimingServiceImpl implements BillTimingService {

	private final static Logger logger = LoggerFactory
			.getLogger(BillTimingServiceImpl.class);
	@Autowired
	private RedisTemplate<String, Serializable> redisTemplate;
	@Autowired
	private EduPayCenter eduPayCenter;
	@Autowired
	private EduPayWexinObserver eduPayWexinObserver;
	@Autowired
	private BillDetailMapper billDetailMapper;
	@Autowired
	BillAlipayMapper billAlipayMapper;
	@Autowired
	BillWeixinMapper billWeixinMapper;

	@Autowired
	EduPayAliObserver eduPayAliObserver;

	private static final String BILLTIMINGKEY = "billTimingKey";
	private static final String BILLTIMINGLOCALKEY = "billTimingLocalKey";
	private static final String BILLTIMINGLOCALVALUE = "billTimingLocalValue";

	@Scheduled(cron = "0 0/5 * * * ?")
	public void timingCloseBill() {

		logger.info("进入定时任务");
		if (redisTemplate.execute(new RedisCallback<Boolean>() {

			@Override
			public Boolean doInRedis(RedisConnection connection) throws DataAccessException {

				return connection.setNX(BillTimingServiceImpl.BILLTIMINGLOCALKEY.getBytes(),
						BillTimingServiceImpl.BILLTIMINGLOCALVALUE.getBytes());
			}
		})) {
			final long timeout = 4 * 60 * 1000;
			redisTemplate.expire(BillTimingServiceImpl.BILLTIMINGLOCALKEY, timeout, TimeUnit.MILLISECONDS); // 设置超时时间，释放内存
			logger.info("过期时间是" + redisTemplate.getExpire(BillTimingServiceImpl.BILLTIMINGLOCALKEY));

			ListOperations<String, Serializable> opsForList = redisTemplate.opsForList();

			int count = opsForList.size(BillTimingServiceImpl.BILLTIMINGKEY).intValue();
			logger.info("--------定时任务关闭账单，查询出" + count + "条");
			for (int j = 0; j < count; j++) {
				// 从redis取出第一条数据
				CloseBillInfo queryCloseBillInfo = (CloseBillInfo) opsForList.index(BillTimingServiceImpl.BILLTIMINGKEY,
						0);
				// 如果这条记录是超时的，才会处理
				if (queryCloseBillInfo != null
						&& queryCloseBillInfo.getBillEndTime().getTime() < System.currentTimeMillis()) {
					// 如果超时则移除这条记录
					CloseBillInfo deleteCloseBillInfo = (CloseBillInfo) opsForList
							.leftPop(BillTimingServiceImpl.BILLTIMINGKEY);
					// 这里更多考虑的是不是和取出的记录是否一样，有并发的考虑
					if (deleteCloseBillInfo.getBillDetailId().equals(queryCloseBillInfo.getBillDetailId())) {
						logger.info("--------账单" + queryCloseBillInfo.getBillDetailId() + "到期时间"
								+ queryCloseBillInfo.getBillEndTime() + "，关闭账单开始");
						BillDetail billDetail = new BillDetail();
						billDetail.setBillDetailId(queryCloseBillInfo.getBillDetailId());
						billDetail = billDetailMapper.selectOne(billDetail);
						// 如果是发送成功的可以关闭，支付成功的只要移除redis就好了
						if (SystemConstans.PAY_WAY_ALI.equals(queryCloseBillInfo.getPayWay())
								&& billDetail.getBillStatus().equals(SystemConstans.BILL_STATUS_SEND_SUCCESS)) {
							BillAlipay billAlipay = new BillAlipay();
							billAlipay.setBillDetailId(billDetail.getBillDetailId());
							billAlipay = billAlipayMapper.selectOne(billAlipay);
							eduPayAliObserver.havePay(billAlipay,
									billAlipay.getSchoolPid(),
									billAlipay.getAlipayOrderNo());
						} else if (SystemConstans.PAY_WAY_WEIXIN.equals(queryCloseBillInfo.getPayWay())
								&& billDetail.getBillStatus().equals(SystemConstans.BILL_STATUS_SEND_SUCCESS)) {
							BillWeixin billWeixin = new BillWeixin();
							billWeixin.setBillDetailId(billDetail.getBillDetailId());
							billWeixin = billWeixinMapper.selectOne(billWeixin);
							eduPayWexinObserver.havePay(billWeixin,
									billDetail.getBillDetailId(),
									billWeixin.getSubMchId());

						}
						logger.info("--------账单" + queryCloseBillInfo.getBillDetailId() + "到期时间"
								+ queryCloseBillInfo.getBillEndTime() + "，关闭账单结束");
					} else {
						break;
					}
				} else {
					break;
				}
			}
		} else {
			logger.info("过期时间是" + redisTemplate.getExpire(BillTimingServiceImpl.BILLTIMINGLOCALKEY));
		}
	}

	/**
	 * 方法描述: 添加扫一扫的账单到redis
	 * 初始作者: 许芬<br/>
	 * 创建日期: 2018年1月24日-下午1:48:52<br/>
	 * 开始版本: 2.0.0<br/>
	 * =================================================<br/>
	 * 修改记录：<br/>
	 * 修改作者 日期 修改内容<br/>
	 * ================================================<br/>
	 *
	 * @param billDetailId
	 * @param billEndTime
	 * @param payWay
	 *            void
	 */
	@Override
	public void addBillToRedisList(String billDetailId, Date billEndTime, String payWay) {

		ListOperations<String, Serializable> opsForList = redisTemplate.opsForList();

		CloseBillInfo closeBillInfo = new CloseBillInfo();
		closeBillInfo.setBillDetailId(billDetailId);
		closeBillInfo.setBillEndTime(billEndTime);
		closeBillInfo.setPayWay(payWay);
		opsForList.rightPush(BillTimingServiceImpl.BILLTIMINGKEY, closeBillInfo);
	}
}
